# DP: ARM: Don't copy uncopyable instructions in gcse.c (backport from the trunk).

gcc/

2009-05-27  Julian Brown  <julian@codesourcery.com>

	* gcse.c (target.h): Include.
	(can_assign_to_reg_without_clobbers_p): Check that the target allows
	copy of argument to a pseudo register.

--- a/src/gcc/gcse.c.orig	2009-04-27 13:55:13.000000000 +0200
+++ b/src/gcc/gcse.c	2009-12-09 11:12:05.000000000 +0100
@@ -172,6 +172,7 @@
 #include "hashtab.h"
 #include "df.h"
 #include "dbgcnt.h"
+#include "target.h"
 
 /* Propagate flow information through back edges and thus enable PRE's
    moving loop invariant calculations out of loops.
@@ -1203,7 +1204,11 @@
 
 static GTY(()) rtx test_insn;
 
-/* Return true if we can assign X to a pseudo register.  */
+/* Return true if we can assign X to a pseudo register.
+
+   Additionally, if the target requires it, check that the resulting insn
+   can be copied.  If it cannot, this means that X is special and probably
+   has hidden side-effects we don't want to mess with.  */
 
 static bool
 can_assign_to_reg_p (rtx x)
@@ -1233,8 +1238,18 @@
      valid.  */
   PUT_MODE (SET_DEST (PATTERN (test_insn)), GET_MODE (x));
   SET_SRC (PATTERN (test_insn)) = x;
-  return ((icode = recog (PATTERN (test_insn), test_insn, &num_clobbers)) >= 0
-	  && (num_clobbers == 0 || ! added_clobbers_hard_reg_p (icode)));
+  
+  icode = recog (PATTERN (test_insn), test_insn, &num_clobbers);
+  if (icode < 0)
+    return false;
+  
+  if (num_clobbers > 0 && added_clobbers_hard_reg_p (icode))
+    return false;
+  
+  if (targetm.cannot_copy_insn_p && targetm.cannot_copy_insn_p (test_insn))
+    return false;
+  
+  return true;
 }
 
 /* Return nonzero if the operands of expression X are unchanged from the
